package com.arpa.wms.controller;

import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.MediaTypes;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.Page;
import com.arpa.ntocc.common.common.constant.StrConsts;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.ShipmentWarehouseValidate;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.ntocc.common.security.annotation.NeedLogin;
import com.arpa.wms.cache.LocationCache;
import com.arpa.wms.domain.consts.CommonConst;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.dto.InventoryDTO;
import com.arpa.wms.domain.entity.Inventory;
import com.arpa.wms.domain.entity.Location;
import com.arpa.wms.domain.enums.TempLocationTypeEnum;
import com.arpa.wms.domain.vo.InventoryImportVO;
import com.arpa.wms.domain.vo.InventoryVO;
import com.arpa.wms.domain.vo.inventory.InventoryYdkwVo;
import com.arpa.wms.service.IGoodsPnService;
import com.arpa.wms.service.IInventoryService;
import com.arpa.wms.service.ILocationService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Maps;
import com.taobao.pac.sdk.cp.dataobject.request.MODUAN_ORDER_CREATE.request;
import io.swagger.annotations.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存 Controller
 * </p>
 *
 * @author LEO
 * @since 2020-08-04
 */
@Api(tags = "库存")
@RestController
@RequestMapping(value="/inventory", produces = "application/json;charset=UTF-8")
@Log4j2
public class InventoryController  {

   private final IInventoryService iInventoryService;

   private final ILocationService locationService;


    @Autowired
    private IGoodsPnService goodsPnService;

    public InventoryController(IInventoryService iInventoryService,
                               ILocationService locationService) {
        this.iInventoryService = iInventoryService;
        this.locationService = locationService;
    }

    /**
     * 获取 库存 列表
     *
     * @param inventoryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "获取 库存 列表", notes = "获取 库存 列表")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
        @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = InventoryVO.class))
    @NeedLogin
    @GetMapping()
    public Result list(InventoryDTO inventoryDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            // 去除只查询正式库存标识，用于查询所有库存
            //登录账号授权的仓库过滤
            inventoryDTO.setGroupCode(UserUtil.getBranchCode());
            //登录账号授权的仓库过滤
            inventoryDTO.setWarehouseCodes(authMap.get(CommonConst.WAREHOUSE_CODES));
            //登录账号授权的货主过滤
            inventoryDTO.setShipmentCodes(authMap.get(CommonConst.SHIPMENT_CODES));

            inventoryDTO.setTempInventory(null);
            if (StrUtil.isNotBlank(inventoryDTO.getGoodsBarCode())) {

                    List<String> shipmentCodes = UserUtil.getAuthorizeShipmentCodes();
                    Set<String> goodsCodeSet = goodsPnService.getGoodsCodeByPn(inventoryDTO.getGoodsBarCode(),shipmentCodes);
                    if(IterUtil.isNotEmpty(goodsCodeSet)){
                        inventoryDTO.setGoodsBarCode("");
                        inventoryDTO.setGoodsCodes(IterUtil.toList(goodsCodeSet));
                    }

            }
            InventoryVO inventoryVOSum = iInventoryService.queryListSum(inventoryDTO);
            List<InventoryVO> inventoryVOList = iInventoryService.queryList(inventoryDTO);
            //汇总库存占用数量和总数量
            InventoryVO sumQuantity = iInventoryService.querySumQuantity(inventoryDTO);

            Map<String, BigDecimal> sumMap = Maps.newHashMap();
            if (null != sumQuantity) {
                BigDecimal totalCanUseQuantity = sumQuantity.getQuantity().subtract(sumQuantity.getUseQuantity());
                sumMap.put("totalQuantity", sumQuantity.getQuantity());
                sumMap.put("totalCanUseQuantity", totalCanUseQuantity);
            }


            Page returnPage = new Page(inventoryDTO.getPageNum(),inventoryDTO.getPageSize());
            returnPage.setRecords(inventoryVOList);
            returnPage.setTotal(inventoryVOSum.getTotal());
            returnPage.setSumObject(sumMap);
            return Result.ok().data(returnPage);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }



    /**
     * 库存 导出数据
     *
     * @param inventoryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "库存 导出数据", notes = "库存 导出数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = InventoryVO.class))
    @NeedLogin
    @GetMapping("/importInventory")
    public Result importInventory(InventoryDTO inventoryDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            // 去除只查询正式库存标识，用于查询所有库存
            //登录账号授权的仓库过滤
            inventoryDTO.setGroupCode(UserUtil.getBranchCode());
            //登录账号授权的仓库过滤
            inventoryDTO.setWarehouseCodes(authMap.get(CommonConst.WAREHOUSE_CODES));
            //登录账号授权的货主过滤
            inventoryDTO.setShipmentCodes(authMap.get(CommonConst.SHIPMENT_CODES));

            InventoryImportVO inventoryImportVO = iInventoryService.importInventorySum(inventoryDTO);
            List<InventoryImportVO> inventoryVOList = iInventoryService.importInventory(inventoryDTO);
            Page returnPage = new Page(inventoryDTO.getPageNum(),inventoryDTO.getPageSize());
            returnPage.setRecords(inventoryVOList);
            returnPage.setTotal(inventoryImportVO.getTotal());
            returnPage.setSumObject(inventoryImportVO);
            return Result.ok().data(returnPage);
        }catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }




    /**
    * 获取库存详情
    *
    * @param code
    * @param request
    * @return
    */
    @ApiOperation(value = "获取库存详情", notes = "获取库存详情")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
        @ApiImplicitParam(name = "code", value = "库存code", paramType = "path", dataType = "String")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = InventoryVO.class))
    @NeedLogin
    @GetMapping(value = "/{code}")
    public Result inventory(@PathVariable String code, HttpServletRequest request) {
        try {
            InventoryVO inventoryVO = iInventoryService.getOneByCode(code);
            return Result.ok().data(inventoryVO);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 修改库存
     * @param entity 库存
     * @param request
     * @return
     */
    @ApiOperation(value = "修改库存", notes = "修改库存")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
        @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PutMapping()
    public Result update(Inventory entity,HttpServletRequest request) {
        if(StringUtils.isBlank(entity.getCode())){
            return Result.error("code不能为空");
        }
        int updateNum = iInventoryService.updateByCode(entity);
        if(updateNum == 0){
            return Result.error("没有更新数据！code:"+entity.getCode());
        }else{
            return Result.ok("修改成功,更新"+updateNum+"条数据！");
        }
    }


    @ApiOperation(value = "获取 库存 ", notes = "获取 库存 ", produces = MediaTypes.JSON_UTF_8)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping(value = "/listInventory")
    public Result listInventory(InventoryDTO inventoryDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            //登录账号授权的仓库过滤
            inventoryDTO.setWarehouseCodes(authMap.get(CommonConst.WAREHOUSE_CODES));
            //登录账号授权的货主过滤 盘点暂时不对货主进行过滤
//            inventoryDTO.setShipmentCodes(UserUtil.getAuthorizeShipmentCodes());
            inventoryDTO.setGroupCode(UserUtil.getBranchCode());
            inventoryDTO.setPageSize(NumConst.NUM_NINETY_NINE_THOUSAND_NINE_HUNDRED_NINETY_NINE);
            List<InventoryVO> inventoryVOList = iInventoryService.queryList(inventoryDTO);
            return Result.ok().data(inventoryVOList);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 批次调整
     * TODO 修改库存后，根据库存状态不可发货更新OMS库存不可用数量
     * @param inventoryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "批次调整 ", notes = "批次调整 ", produces = MediaTypes.JSON_UTF_8)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
    })
    @NeedLogin
    @PostMapping(value = "/lotAdjust")
    public Result lotAdjust(@RequestBody InventoryDTO inventoryDTO, HttpServletRequest request) {
        try {
            Result adjustResult = iInventoryService.lotAdjust(inventoryDTO);
            return adjustResult;
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }



    /**
     * 锁定库存
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "锁定库存", notes = "锁定库存")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "code", value = "库存code", paramType = "path", dataType = "String")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = Inventory.class))
    @NeedLogin
    @GetMapping(value = "/lock/{code}")
    public Result lockInventory(@PathVariable String code, HttpServletRequest request) {
        try {
            iInventoryService.lock(code);
            return Result.ok();
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 解锁库存
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "解锁库存", notes = "解锁库存")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer 123456"),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "code", value = "库存code", paramType = "path", dataType = "String")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = Inventory.class))
    @NeedLogin
    @GetMapping(value = "/unlock/{code}")
    public Result unlockInventory(@PathVariable String code, HttpServletRequest request) {
        try {
            iInventoryService.unlock(code);
            return Result.ok();
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 获取可移位库存
     * @param inventoryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "获取可移位 库存 ", notes = "获取可移位 库存 ", produces = MediaTypes.JSON_UTF_8)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @GetMapping(value = "/listCanMoveInventory")
    public Result listCanMoveInventory(InventoryDTO inventoryDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            // 根据仓库，找到退减库位，加入到条件中。 退减库位虽然是临时库位，但里面的库存可以做移位操作。
            //登录账号授权的仓库过滤
            inventoryDTO.setGroupCode(UserUtil.getBranchCode());
            //登录账号授权的仓库过滤
            inventoryDTO.setWarehouseCodes(authMap.get(CommonConst.WAREHOUSE_CODES));
            //登录账号授权的货主过滤
            inventoryDTO.setShipmentCodes(authMap.get(CommonConst.SHIPMENT_CODES));

            Location location = locationService.getTempLocation(inventoryDTO.getWarehouseCode(), TempLocationTypeEnum.RE);
            String locations = location.getCode();
            inventoryDTO.setTempLocations(locations);
            InventoryVO inventoryVoSum = iInventoryService.queryCanMoveListSum(inventoryDTO);
            List<InventoryVO> inventoryVOList = iInventoryService.queryCanMoveList(inventoryDTO);

            Page returnPage = new Page(inventoryDTO.getPageNum(),inventoryDTO.getPageSize());
            returnPage.setRecords(inventoryVOList);
            returnPage.setTotal(inventoryVoSum.getTotal());
            returnPage.setSumObject(inventoryVoSum);
            return Result.ok().data(returnPage);

        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 获取 库存 列表
     *
     * @param inventoryDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "获取 库存 导出 列表", notes = "获取 库存 导出 列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = InventoryVO.class))
    @NeedLogin
    @GetMapping("/exportInventoryList")
    public Result printInventoryList(InventoryDTO inventoryDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            //登录账号授权的仓库过滤
            inventoryDTO.setWarehouseCodes(authMap.get(CommonConst.WAREHOUSE_CODES));
            //登录账号授权的货主过滤
            inventoryDTO.setShipmentCodes(authMap.get(CommonConst.SHIPMENT_CODES));
            inventoryDTO.setGroupCode(UserUtil.getBranchCode());
            inventoryDTO.setTempInventory(null);
            inventoryDTO.setPageNum(NumConst.NUM_ONE);
            inventoryDTO.setPageSize(Integer.MAX_VALUE);
            List<InventoryVO> inventoryVOList = iInventoryService.queryList(inventoryDTO);
            inventoryVOList.stream().forEach(e -> {
                e.setCanUseQuantity(e.getQuantity().subtract(e.getUseQuantity()));
            });

            Page returnPage = new Page(inventoryDTO.getPageNum(),inventoryDTO.getPageSize());
            returnPage.setRecords(inventoryVOList);
            return Result.ok().data(returnPage);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
            return Result.error(e.getMessage());
        }
    }





}
